C言語でEfiMainを書く (1章:P43)
オプションが大量に・・・
code:build-command
$ clang -target x86_64-pc-win32-coff -mno-red-zone -fno-stack-protector -fshort-wchar -Wall -c ../src/hello.c
$ lld-link /subsystem:efi_application /entry:EfiMain /out:hello.efi hello.o
$ run_qemu.sh hello.efi
そもそも-mはmode、-fはflag
-mno-red-zoneも-fno-stack-protectorもフラグに見えるけど・・・
-mno-red-zone
とりあえずred zoneが何なのかわからない
レッドゾーンはアクセス不能
スレッドライブラリで生成される各スレッドスタックには、レッドゾーンがあります。スレッドライブラリはレッドゾーンとして、スタックオーバーフローを補足するためのページをスタックの一番上に付加します。このページは無効で、アクセスされるとメモリーフォルトになります。レッドゾーンは、自動的に割り当てられるすべてのスタックに付加されます。これは、その大きさがアプリケーションで指定されたかデフォルトの大きさかに関係なく行われます
「レッドゾーンとして、スタックオーバーフローを補足するためのページをスタックの一番上に付加」というのが重要な気がする
The 128-byte area beyond the location pointed to by %rsp is considered to be reserved and shall not be modified by signal or interrupt handlers. Therefore, functions may use this area for temporary data that is not needed across function calls. In particular, leaf functions may use this area for their entire stack frame, rather than adjusting the stack pointer in the prologue and epilogue. This area is known as the red zone.
「rsp(x86_64におけるスタックポインタ)の128バイト先はレッドゾーンと呼ばれる予約済み領域」とのこと
これはいわゆるコンパイラによる最適化で、ユーザーランドでは重宝することが多いものの、カーネル空間で割り込みが発生することを考慮するとややこしくなるらしい?
このサイトはWhyというかHowが書いてあるっぽい
(2022/01/23追記) P81に説明があった [rsp-??]みたいな記述は見た覚えがあったから、-mno-red-zoneでこれがなくなるのか!?と思ったけど、そんなことはなかった
https://scrapbox.io/files/620ce0a1d9e95f001d895ed4.png
-fno-stack-protector
スタックのローカル変数のスロットの前に、スタックプロテクタという領域を用意し、スタック領域がスタックプロテクタを超えてアクセス(というか、スタックプロテクタを踏んでしまった場合)を検知し、もしスタックプロテクタに格納されている値が関数の呼び出し時と関数から戻る時に異なっていた場合は、スタック領域を破壊したということで問題が発生したということにする。 これがスタックプロテクタの役割
-fshort-wchar
まあたぶんEFIの仕様が1文字あたり16ビットなUCS-2だから (P39)、文字列をそう解釈してコンパイルしてくれるんじゃないかな→ちょっと違いそう
そもそもL”Hello, World!”のL prefixを気にする必要がある
”str”の型はchar[N}に対し、L”str”の型はwchar_t[N]
clangのデフォルトは-fnoshort-wcharで、これはwchar_tを4バイトとするもの
-fshort-wcharはwchar_tを2バイトにするオプションらしい
shortは言語仕様では16ビット→2バイト以上でなければいけないらしいけど、shortとwchar_tは関係あるんだろうか
/subsystem:
efi_application用なんだろうなというのはわかるけど、それ以外何があるのか気になる
windowsやconsoleがあるらしい
公式ドキュメントっぽいのにも見当たらないし、ld-lldばっかり出てしまう
lld-link -helpの結果は /subsystem:<value> Specify subsystem らしいけど